# -*- coding: utf-8 -*-
# author : hxt
#   date : 2025/3/4
'''
excel用例参数化

读取excel的数据
'''
import ast
import copy
import json
import os.path

import pandas as pd,uuid
import yaml

from apirun.core.globalContext import g_context



def load_context_from_excel(folder_path):
    '''

    :param folder_path: 文件路径（文件夹）
    :return:
    '''
    try:
        excel_file_path = os.path.join(folder_path,'context.xlsx') #把2个文件进行拼接
        # 读取excel
        df = pd.read_excel(excel_file_path)

        data = {
            "_database":{}
        }

    #     遍历excel - 类型、变量描述、变量值
        for index,row in df.iterrows():
    #         如果是变量，直接存 -- 变量名：value
            if row['类型'] == '变量': data[row['变量描述']] = row['变量值']
            elif row['类型'] == '数据库':
                db_name = row['变量描述']
                db_config = json.loads(row['变量值'])
                data['_database'].update({db_name:db_config})
        g_context().set_by_dict(data) #写入到全局变量
    except Exception as e:
        print(f'装载excel文件错误：{str(e)}')
        return False

# load_context_from_excel(r'D:\hxt\pywork\auto_api\apirun202504ddt\testcase')

def load_excel_files(config_path):
    '''
    加载满足条件的文件及数据（ xxx(数字）_用例.xlsx）
    :param config_path: excel用例存放的路径
    :return:
    '''
    excel_caseInfos = []  #存储所有的数据
    suite_dir = os.path.join(config_path)

    # 加载全局变量
    load_context_from_excel(suite_dir)

    # 扫描文件夹下的excel，获取文件夹下所有的excel文件
    file_list = [(int(i.split('_')[0]), i) for i in os.listdir(suite_dir) if i.endswith('.xlsx') and i.split('_')[0].isdigit()]
    # 文件按数字编号排序，并只保留文件名
    file_list.sort()
    file_list = [i[-1] for i in file_list]

    # 读取维护的keywords.yaml文件，以便后面的值一一对应起来
    current_dir = os.path.dirname(__file__)  # 获取当前文件路径
    parent_dir = os.path.dirname(current_dir)  # 基于当前路径获取上一级路径
    keywords_file_path = os.path.join(parent_dir, 'extend/keywords.yaml')

    with open(keywords_file_path,'r',encoding='utf-8') as f:
        keywords_info = yaml.full_load(f)

    # 加载每个文件的数据给到excel_caseInfos
    for i in file_list:
        file_path = os.path.join(suite_dir,i)
        data = pd.read_excel(file_path,sheet_name=0)
        data = data.where(data.notnull(),None)
        data = data.to_dict(orient='records')  #以字典形式显示读取的数据
        # print(data)

        # 初始化一个字典，用例存放某一条测试用例
        current_test_case = None

        for row in data:
            if row['测试用例标题']:
                if current_test_case: #若已构建完毕，需要添加到对应的用例中
                    excel_caseInfos.append(current_test_case)

                #初始化一个测试用例字典
                current_test_case ={
                    'desc':row['测试用例标题'],
                    'featureName':row['一级模块'],
                    'storyName':row['二级模块'],
                    'steps':[]
                }

            # 开始写步骤 - 封装关键字及其参数
    #         1、初始化步骤的值
            steps = {
                row['步骤描述']:{
                    '关键字':row['关键字']
                }
            }

    #         2、提取关键字的参数
            parameters = []
            for k,v in row.items():
                if '参数_' in k:
                    try:
                        v = ast.literal_eval(v)
                    except:
                        pass
                    parameters.append(v)

            step = {k:v for k,v in zip(keywords_info[row['关键字']],parameters)}
            steps[row['步骤描述']].update(step)

            # 将步骤添加到当前用例
            current_test_case['steps'].append(steps)

        if current_test_case:
            excel_caseInfos.append(current_test_case)

    return excel_caseInfos

def excel_case_parser(config_path):
    '''
    把excel格式处理成我们规定的格式
    :param config_path:文件路径
    :return:
            {
                "case_infos":case_infos,   #所有的测试用例 []
                "case_names":case_names    #所有测试用例对应的标题 []
            }
    '''
    case_infos = []
    case_names = []

    excel_case_infos = load_excel_files(config_path)

    for case_info in excel_case_infos:
        # 获取用例标题
        case_info.update({'_case_name': case_info['desc']})
        case_infos.append(case_info)
        case_names.append(case_info['desc'])
    return {
        'case_infos':case_infos,
        'case_names':case_names
    }
